$include("/com/opesoft/fw/validate/serverValidate.ojs");

function ValidateConfig(ruleFile)
{
	this.ruleFile=ruleFile;
	this.xml=null;
	this.queue=new Array();  //初始化前缓存Validate队列
	this.initd=false;  //已经初始化

	var self=this;

	//取回验证规则
	this._init=function(text,xml)
	{
		self.xml=xml;

		if(self.queue.length>0)
		{
			for(var i=0;i<self.queue.length;i++)
			{
				self.queue[i].check();
			}
			this.queue=new Array();
		}
	}
}

//初始化
ValidateConfig.prototype.init=function()
{
	this.initd=true;
	var myAjax=new Ajax(this.ruleFile,{method:'get',onComplete:this._init});
	myAjax.request();
}


ValidateConfig.prototype.check=function(name,form,callback)
{
	//构造Validate对象
	var validate=new Validate();
	validate.name=name;
	if($type(form)=='string') validate.form=$(document.forms[form]);
	else validate.form=form;
	validate.callback=callback;
	validate.config=this;

	if(this.xml==null)
	{
		this.queue.push(validate);
		if(!this.initd) this.init();
	}
	else validate.check();
}

ValidateConfig.prototype.serverRules=
{
	unique:"com.opesoft.pf.rules.UniqueRule"
}

ValidateConfig.prototype.rules=
{
	required:function(v,ps)  //必填项
	{
		if(v==null || (v+"").trim()=="")
			return "${name} can't be empty!";
	},
	string:function(v,ps)
	{
		if(ps['min']!=null && v.length<parseInt(ps['min']))
			return "${name}'s length must be more than "+ps['min'];
		if(ps['max']!=null && v.length>parseInt(ps['max']))
			return "${name}'s length must be less than "+ps['max'];
		if(ps['value']!=null && v!=ps['value'])
			return "${name}'s value must is："+ps['value'];
	},
	integer:function(v,ps)  //整数
	{
		if(v!=null && v.trim()!="")
		{
			if(!(/^-?\d+$/.test(v)))
				return "${name} must be a Integer";
			if(ps['min']!=null && parseInt(v)<parseInt(ps['min']))
				return "${name} can't be less than "+ps['min'];
			if(ps['max']!=null && parseInt(v)>parseInt(ps['max']))
				return "${name} can't be more than "+ps['max'];
		}
	},
	number:function(v,ps)  //数字
	{
		if(v!=null && v.trim()!="")
		{
			if(!(/^-?\d+.?\d*$/.test(v)))
				return "${name} must be a Number";
			if(ps['min']!=null && parseFloat(v)<parseFloat(ps['min']))
				return "${name} can't be less than "+ps['min'];
			if(ps['max']!=null && parseFloat(v)>parseFloat(ps['max']))
				return "${name} can't be more than "+ps['max'];
		}
	},
	date:function(v,ps)  //日期 yyyy-mm-dd
	{
		if(v!=null && v.trim()!="")
		{
			if(v.length!=10 || !(/\d{4}-[0|1]\d-[0-3]\d/.test(v)))
				return "${name} must be a date. Format：yyyy-mm-dd";
			if(ps['min']!=null && v<ps['min'])
				return "${name} can't be less than "+ps['min'];
			if(ps['max']!=null && v>ps['max'])
				return "${name} can't be more than "+ps['max'];
		}
	},
	custom:function(v,ps)  //自定义
	{
		if(v!=null && v.trim()!="")
		{
			if(ps['expr']!=null)
			{
				var expr;
				eval('expr='+ps['expr']);
				if(!(expr.test(v)))
				{
					if(ps['msg']!=null)
						return ps['msg'];
					else
						return "${name}'s value isn't right";
				}
			}
		}
	}
}

/**********************************/

function Validate()
{
	this.config;  //所属的ValidateConfig
	this.result=null;  //存放验证的结果，如果完全通过应该为null

	//进行验证的参数
	this.name;
	this.form;
	this.callback;

	this._checking=0;  //正在验证的Rule的数目，只记录服务器端验证

	var self=this;

	//用于处理服务器端验证的结果
	this.serverRuleResult=function(result,data)
	{
		self._checking--;
		self.ruleResult(result,data.fieldId,data.fieldName,data.rule.childNodes,data.rule.tagName);
		self.completeCheck();
	}
}


Validate.prototype.check=function()
{
	try
	{
		var validate=this.findValidate();
		if(validate!=null)
		{
			//验证一级field节点的数据
			var fields=validate.childNodes;  //form中的子节点
			for(var i=0;i<fields.length;i++)
			{
				if(fields[i].tagName=="field")  //子节点名为field时，执行验证
				{ 
					this.checkField(fields[i]);
				}
			}
		}
		else
		{
			alert("Can't find validate rules ["+this.name+"] in "+this.config.ruleFile);	
			return;
		}
	}
	catch(e)
	{
		alert("Error in Validate.check() : "+e.message);
		return;
	}

	this.completeCheck();
}

Validate.prototype.findValidate=function()
{
	var validates=this.config.xml.getElementsByTagName('validate');
	if(validates!=null && validates.length>0)
	{
		for(var i=0;i<validates.length;i++)
		{
			if(validates[i].getAttribute('name')==this.name)
				return validates[i];
		}
	}
}

//读取一级节点field
Validate.prototype.checkField=function(field) 
{
	var fieldId=field.getAttribute("id");  //字段ID
	var fieldName=field.getAttribute("name");  //字段名称
	var rules=field.childNodes;  //要求的规则
	this.checkRules(fieldId,fieldName,rules);
}

//执行一组验证
Validate.prototype.checkRules=function fun(fieldId,fieldName,rules)
{
	if(rules!=null && rules.length>0)
	{
		//验证每个规则
		for(var j=0;j<rules.length;j++)
		{
			var tagName=rules[j].tagName;
			if(tagName=="rule" || tagName=="if" || tagName=="ifnot")  //可以处理Rule、If、Ifnot三种标签
			{
				var rule=rules[j];  //规则节点
				this.checkRule(fieldId,fieldName,rule);  //检验属性是否符合验证规则
			}
		}
	}
}

//检验属性是否符合验证规则
Validate.prototype.checkRule=function fun(fieldId,fieldName,rule)
{
	var ruleName=rule.getAttribute("name");  //规则名称
	var fieldId2=rule.getAttribute("field");  //如果传入的值不是针对当前字段的，取Field属性做为取值表单的ID
	var fieldValue=this.form.getElement('[name='+(fieldId2==null?fieldId:fieldId2)+']').getValue(); //表单属性值
	$debug(fieldId+" : "+fieldValue);

	var parameters={};  //规则参数
	{
		var attributes=rule.attributes;
		if(attributes!=null)
		{
			for(var n=0;n<attributes.length;n++)
			{
				var attribute=attributes[n];

				//这段代码实现的是取回XML中的属性值，并把${xxx}这样的变量用Input中的值取代了
				var v=attribute.value;
				if(v!=null && v.indexOf("${")>-1)
				{
					var a1=v.split("${");
					if(a1.length>0)
					{
						v=a1[0];
						for(var k=1;k<a1.length;k++)
						{
							var a2=a1[k].split("}");
							if(a2.length>1)
							{
								var inputField=this.form.getElement('[name='+a2[0]+']');
								var inputValue=inputField==null?null:inputField.getValue();
								if(inputValue!=null)
									v+=inputValue;
								else
									v+="${"+a2[0]+"}";
							}
							else
							{
								if(a2.length>0)
									v+="${"+a2[0];
								else
									v+="${";
							}

							for(var j=1;j<a2.length;j++)
							{
								v+=a2[j]+(j==a2.length-1?"":"}");
							}
						}
					}
					$debug(attribute.name+" : "+v);
				}
				parameters[attribute.name]=v;
			}
		}		
	}
	
	if(this.config.rules[ruleName]!=null)  //内部支持的验证规则中存在指定的规则时
	{
		var result=this.config.rules[ruleName](fieldValue,parameters);  //执行指定的规则验证
		this.ruleResult(result,fieldId,fieldName,rule.childNodes,rule.tagName);  //规则验证结果处理
	}
	else  //内部支持的验证规则中不存在指定的规则时，调用外部规则
	{
		//this.checkRemoteRule(ruleName,fieldValue,parameters,rule);
		if(this.config.serverRules[ruleName]!=null)
			ruleName=this.config.serverRules[ruleName];
		
		var data={};
		data['rule']=rule;
		data['fieldId']=fieldId;
		data['fieldName']=fieldName;

		this._checking++;
		ServerValidate.check(ruleName,fieldValue,parameters,this.serverRuleResult,data);
	}
}

/*
用于处理验证的结果
参数：
result : 验证的结果，如果没有错误的话为null
fieldId : 当前验证字段的ID
fieldName : 当前验证字段的Name
childRules : 如果包含有子验证，这里是子验证的集合
tagName : 标签的名称，可以是：rule,if,ifnot
*/
Validate.prototype.ruleResult=function(result,fieldId,fieldName,childRules,tagName)
{
	var right=(result==null || result.trim()=='')?true:false;  //检验的结果是否正确

	//区别不同的标签
	var condition=null;
	if(tagName=='if')
		condition=true;
	else if(tagName=='ifnot')
		condition=false;

	//如果是对Rule的检查，需要把错误信息记录下来
	if(condition==null && !right)
	{
		if(result!=null && result!='')
		{
			result=result.replace('${name}',fieldName);

			if(this.result==null) this.result={};

			if(this.result[fieldId]!=null)
				this.result[fieldId]+="\n"+result;
			else
				this.result[fieldId]=result;
		}
	}

	if(right || (condition==false && !right))  //是否执行子验证
	{
		//如果有下级的检查规则，执行之
		if(childRules!=null && childRules.length>0)
		{
			this.checkRules(fieldId,fieldName,childRules);
		}
	}
}

//完成验证后的动作
Validate.prototype.completeCheck=function()
{
	if(this._checking<1)  //确认没有在在进行的后台验证
	{
		if(this.callback!=null)
			this.callback(this.result);
		else
		{
			var msg="";
			for(key in this.result)
			{
				if(msg=="")
					msg+=this.result[key];
				else
					msg+="\n"+this.result[key];
			}
			if(msg!="") alert(msg);
		}
	}
}

/*******************************/

function FormWrapper(formName)
{
	this.formName=formName;
	this.errorImages=new Array();

	this.errorImg=$_.contextPath+'/opesoft/images/error.png';

	var self=this;

	//根据验证的结果显示错误信息
	this.showErrors=function(result)
	{
		self.clearErrors();

		if(result!=null)
		{
			for(key in result)
			{
				var img=document.createElement('IMG');
				img.src=self.errorImg;
				img.alt=result[key];
				img.title=img.alt;
				img.style.cursor='pointer';
				img.onclick=function(){alert(this.title)};

				//如果有放错误信息的地方，就放在这个位置
				var field=$(document.forms[self.formName]).getElement('[id='+key+'_error]');
				if(field!=null)
					field.appendChild(img);
				else
				{
					//否则尝试放在输入表单的后面
					var field=$(document.forms[self.formName]).getElement('[name='+key+']');
					if(field!=null)
						$(img).injectAfter(field);
				}

				//记录下来错误信息对象，用于清除时使用
				if(field!=null)
					self.errorImages.push(img);
			}
		}
	}

	//清除错误信息
	this.clearErrors=function()
	{
		if(self.errorImages!=null && self.errorImages.length>0)
		{
			for(var i=0;i<self.errorImages.length;i++)
			{
				self.errorImages[i].parentNode.removeChild(self.errorImages[i]);
			}
			self.errorImages=new Array();
		}
	}

	this.reset=function()
	{
		$(document.forms[self.formName]).reset();
		self.clearErrors();
	}
}





